其他

奇虎360正式开源其高性能KV存储平台Zeppelin

2018-01-27 开源最前线

开源最前线(ID:OpenSourceTop) 猿妹 整编

素材来自:http://catkang.github.io/2018/01/07/zeppelin-overview.html


奇虎360正式开源其高性能KV存储平台Zeppelin,本文就将从技术细节方面来进行介绍。


高性能 KV 存储平台 Zeppelin


授权协议:Apache 2.0

开发语言:C/C++

操作系统:跨平台

GitHub地址:https://github.com/Qihoo360/zeppelin



Zeppelin 简介


Zeppelin 是由奇虎 Pika 实验室和 DBA 团队开发和维护的分布式 Key-Value 平台,设计灵感来自 Pika 和Ceph 。Zeppelin 旨在提供高性能,高可靠性和高可扩展性的 KV 存储服务。基于 Zeppelin ,可以轻松构建其他服务,如 Table Store,S3 或 Redis 。



API 设计


为了让读者对Zeppelin有个整体印象,先介绍下其提供的接口:

● 基本的KV存储相关接口:Set、Get、Delete;

● 支持TTL;

● HashTag及针对同一HashTag的Batch操作,Batch保证原子,这一支持主要是为了支撑上层更丰富的协议。



数据分布


最为一个分布式存储,首要需要解决的就是数据分布的问题。Zeppelin选择了比较灵活的分片的方式,如下图所示:



用逻辑概念Table区分业务,并将Table的整个Key Space划分为相同大小的分片(Partition),每个分片的多副本分别存储在不同的存储节点(Node Server)上,因而,每个Node Server都会承载多个Partition的不同副本。


Partition个数在Table创建时确定,更多的Partition数会带来更好的数据均衡效果,提供扩展到更大集群的可能,但也会带来元信息膨胀的压力。实现上,Partition又是数据备份、数据迁移、数据同步的最小单位,因此更多的Partition可能带来更多的资源压力。Zeppelin的设计实现上也会尽量降低这种影响。


可以看出,分片的方式将数据分布问题拆分为两层隐射:从Key到Partition的映射可以简单的用Hash实现。而Partition副本到存储节点的映射相对比较复杂,需要考虑稳定性、均衡性、节点异构及故障域隔离(更多讨论见浅谈分布式存储系统数据分布方法)。关于这一层映射,Zeppelin的实现参考了CRUSH对副本故障域的层级维护方式,但摈弃了CRUSH对降低元信息量稍显偏执的追求。


在进行创建Table、扩容、缩容等集群变化的操作时,用户需要提供整个:

● 集群分层部署的拓扑信息(包含节点的机架、机器等部署信息);

● 存储节点权重;

● 各个故障层级的分布规则;

● Zeppelin根据这些信息及当前的数据分布直接计算出完整的目标数据分布,这个过程会尽量保证数据均衡及需要的副本故障域。下图举例展示了,副本在机架(cabinet)级别隔离的规则及分布方式。




元信息管理


上面确定了分片的数据分布方式,可以看出,包括各个分片副本的分布情况在内的元信息需要在整个集群间共享,并且在变化时及时扩散,这就涉及到了元信息管理的问题,通常有两种方式:


● 有中心的元信息管理:由中心节点来负责整个集群元信息的检测、更新和维护,这种方式的优点是设计简洁清晰,容易实现,且元信息传播总量相对较小并且及时。最大的缺点就是中心节点的单点故障。以BigTable和Ceph为代表。


● 对等的元信息管理:将集群元信息的处理负担分散到集群的所有节点上去,节点间地位一致。元信息变动时需要采用Gossip等协议来传播,限制了集群规模。而无单点故障和较好的水平扩展能力是它的主要优点。Dynamo和Redis Cluster采用的是这种方式。


考虑到对大集群目标的需求,Zeppelin采用了有中心节点的元信息管理方式。其整体结构如下图所示:


可以看出Zeppelin有三个主要的角色,元信息节点Meta Server、存储节点Node Server及Client。Meta负责元信息的维护、Node的存活检测及元信息分发;Node负责实际的数据存储;Client的首次访问需要先从Meta获得当前集群的完整数据分布信息,对每个用户请求计算正确的Node位置,并发起直接请求。


为了减轻上面提到的中心节点的单点问题。我们采取了如下策略:

● Meta Server以集群的方式提供服务,之间以一致性算法来保证数据正确。

● 良好的Meta设计:包括一致性数据的延迟提交;通过Lease让Follower分担读请求;粗粒度的分布式锁实现;合理的持久化及临时数据划分等。

● 智能Client:Client承担更多的责任,比如缓存元信息;维护到Node Server的链接;计算数据分布的初始及变化。

● Node Server分担更多责任:如元信息更新由存储节点发起;通过MOVE,WAIT等信息,实现元信息变化时的客户端请求重定向,减轻Meta压力。


通过上面几个方面的策略设计,尽量的降低对中心节点的依赖。即使Meta集群整个异常时,已有的客户端请求依然能正常进行。



一致性算法


上面已经提到,中心元信息Meta节点以集群的方式进行服务。这就需要一致性算法来保证:


即使发生网络分区或节点异常,整个集群依然能够像单机一样提供一致的服务,即下一次的成功操作可以看到之前的所有成功操作按顺序完成。


Zeppelin中采用了我们的一致性库Floyd来完成这一目标,Floyd是Raft的C++实现。更多内容可以参考:Raft和它的三个子问题。


利用一致性协议,Meta集群需要完成Node节点的存活检测、元信息更新及元信息扩散等任务。这里需要注意的是,由于一致性算法的性能相对较低,我们需要控制写入一致性库的数据,只写入重要、不易恢复且修改频度较低的数据。



副本策略


为了容错,通常采用数据三副本的方式,又由于对高性能的定位,我们选择了Master,Slave的副本策略。每个Partition包含至少三个副本,其中一个为Master,其余为Slave。所有的用户请求由Master副本负责,读写分离的场景允许Slave也提供读服务。Master处理的写请求会在修改DB后写Binlog,并异步的将Binlog同步给Slave。



上图所示的是Master,Slave之间建立主从关系的过程,右边为Slave。当元信息变化时,Node从Meta拉取最新的元信息,发现自己是某个Partition新的Slave时,将TrySync任务通过Buffer交给TrySync Moudle;TrySync Moudle向Master的Command Module发起Trysync;Master生成Binlog Send任务到Send Task Pool;Binlog Send Module向Slave发送Binlog,完成数据异步复制。更详细内容见:Zeppelin不是飞艇之存储节点。未来也考虑支持Quorum及EC的副本方式来满足不同的使用场景。



数据存储


Node Server最终需要完成数据的存储及查询等操作。Zeppelin目前采用了Rocksdb作为存储引擎,每个Partition副本都会占有独立的Rocksdb实例。采用LSM方案也是为了对高性能的追求,相对于B+Tree,LSM通过将随机写转换为顺序写大幅提升了写性能,同时,通过内存缓存保证了相对不错的读性能。庖丁解LevelDB之概览中以LevelDB为例介绍了LSM的设计和实现。


然而,在数据Value较大的场景下,LSM写放大问题严重。为了高性能,Zeppelin大多采用SSD盘,SSD的随机写和顺序写之间的差距并不像机械盘那么大,同时SSD又有擦除寿命的问题,因此LSM通过多次重复写换来的高性能优势不太划算。而Zeppelin需要对上层不同协议的支撑,又不可避免的会出现大Value,LSM upon SSD针对这方面做了更多的讨论,包括这种改进在内的其他针对不同场景的存储引擎及可插拔的设计也是Zeppelin未来的发展方向。



故障检测


一个好的故障检测的机制应该能做到如下几点:

● 及时:节点发生异常如宕机或网络中断时,集群可以在可接受的时间范围内感知;

● 适当的压力:包括对节点的压力,和对网络的压力;

● 容忍网络抖动

● 扩散机制:节点存活状态改变导致的元信息变化需要通过某种机制扩散到整个集群;


Zeppelin 中的故障可能发生在元信息节点集群或存储节点集群,元信息节点集群的故障检测依赖下层的Floyd的Raft实现,并且在上层通过Jeopardy阶段来容忍抖动。


而存储节点的故障检测由元信息节点负责, 感知到异常后,元信息节点集群修改元信息、更新元信息版本号,并通过心跳通知所有存储节点,存储节点发现元信息变化后,主动拉去最新元信息并作出相应改变。


最后,Zeppelin还提供了丰富的运维、监控数据,以及相关工具。方便通过Prometheus等工具监控展示。


附:新开源报道汇总

《【新开源报道 42】Facebook开源自家 AR 核心技术,能快速识别影片中的物体》

《【新开源报道 41】阿里正式开源动态非侵入 AOP 解决方案 JVM-Sandbox》

《【新开源报道 40】OpenAI 开源最新工具包,十倍模型计算时间仅增20%》

《【新开源报道 39】Mozilla 开源稍后阅读应用 Pocket 代码》

《【新开源报道 38】那个被美国通缉的程序员,开发了一款保护你隐私的 App》

《【新开源报道 37】Facebook 开源语音识别工具包wav2letter》

《【新开源报道 36】有效减少错误代码!Instagram 开源用于 Python 3 的 MonkeyType 工具》

《【新开源报道 35】国内第一家私有视频通信软件 Tucodec 开源》

《【新开源报道 34】AMD 开源基于 Mesa 的 Vulkan Linux 驱动》

《【新开源报道 33】安全软件公司 Avast 开源机器码反编译器 RetDec》

《【新开源报道 32】谷歌开源 TFGAN:轻量级生成对抗网络工具库》

《【新开源报道 31】国内首套开源持续集成(CI) 解决方案 flow.ci 开源啦》

《【开源推荐 30】苹果开源领域又一深造:开源机器学习框架 Turi Create》

《【新开源推荐 29】AI开发者的福音:360公司宣布开源深度学习调度平台 XLearning!》

《【新开源推荐 28】百度正式开源 Linux 发行版 MesaLock Linux》

《【新开源报道 27】百度开源高性能 Python 分布式计算框架 Bigflow》

《【新开源报道 26】滴滴开源基于 Vue.js 的移动端组件库 cube-ui》

《【新开源报道 25】Google 开源 Docker 镜像差异分析工具 container-diff》

《【新开源报道 24】美团点评开源MySQL闪回工具 —— MyFlash》

《【新开源报道 23】IBM 推出首套开源现代化字体 —— IBM Plex》

《【新开源报道 22】Microsoft 开源用于 VS Code 的 Java Debugger》

《【新开源报道 21】阿里开源容器技术Pouch和P2P文件分发系统“蜻蜓”》

《【新开源报道 20】Uber正式开源其分布式跟踪系统Jaeger》

《【新开源报道 19】Uber与斯坦福大学开源深度概率编程语言Pyro》

《【新开源报道 18】谷歌开放内部工具 Colaboratory 来协助 AI 开发》

《【新开源报道 17】这波开源满分!清华大学开源网络嵌入的工具包 —— OpenNE

《【新开源报道 16】AI开发者福音!微软亚马逊联合发布深度学习库 Gloun》

《【新开源报道 15】谷歌发布量子开源软件,量子计算机对科学家免费开放 》

《【新开元报道 14】微软开源用于Spark的深度学习库MMLSpark》

《【新开源报道 13】Facebook 开源帮助开发者消灭最顽固的软件 bug 的工具》

《【新开源报道 12】不只是阿里巴巴的操作系统,AliOS 宣布开源》

《【新开源报道 11】重磅!阿里巴巴正式开源全球化OpenMessaging和ApsaraCache项目》

《【新开源报道 10】IBM 和谷歌等巨头联手为开发者推出开源容器安全工具Grafeas》

《【新开源报道 9】Google开源Abseil,为C++和Python开发提供支持》

《【新开源报道 8】serverless 领域的福音!Oracle 宣布开源 Fn project》

《【新开源报道 7】苹果在 GitHub 上公布 macOS 和 iOS 内核源码》

《【新开源报道 6】百度开源移动端深度学习框架mobile-deep-learning(MDL)》

《【新开源报道 5】百度正式开源其 RPC 框架 brpc》

《【新开源报道 4】IBM 开源动态的应用服务器运行时环境 Open Liberty》

《【新开源报道 3】微信后台团队最近开源力作:PhxQueue分布式队列》

《【新开源报道 2】喜大普奔!阿里即将开源 ApsaraCache,云数据库 Redis 版分支》

【新开源报道 1】腾讯 Web UI 解决方案 QMUI Web 正式回迁开源》



●本文编号154,以后想阅读这篇文章直接输入154即可

●输入m获取文章目录

↓↓↓ 点击"阅读原文" 进入GitHub详情页 

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存